local extension=Package("xiaobai_sgs48")
extension.extensionName="xiaobai"

Fk:loadTranslationTable{
  ["xiaobai_sgs48"] = "SGS48",
}

local U = require "packages/utility/utility"

local function AddWinAudio(general)
  local Win = fk.CreateActiveSkill{ name = general.name.."_win_audio" }
  Win.package = extension
  Fk:addSkill(Win)
end

local zhaoyu = General(extension, "xiaobai__zhaoyu", "qun", 3, 3, General.Female)
local huihao = fk.CreateViewAsSkill{
  name = "xiaobai__huihao",
  anim_type = "offensive",
  prompt = "#xiaobai__huihao",
  card_filter = function(self, to_select, selected)
    return #selected == 0 and Fk:getCardById(to_select):getMark("@@xiaobai__huihao-inhand-turn") > 0
  end,
  view_as = function(self, cards)
    if #cards ~= 1 then return end
    local card = Fk:cloneCard("slash")
    card:addSubcard(cards[1])
    card.skillName = self.name
    return card
  end,
  enabled_at_response = function (self, player, response)
    return not response
  end,
}
local huihao_trigger = fk.CreateTriggerSkill{
  name = "#xiaobai__huihao_trigger",
  anim_type = "control",
  events = {fk.EventPhaseStart},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and player.phase == Player.Start
  end,
  on_use = function (self, event, target, player, data)
    local room = player.room
    player:drawCards(1, self.name)
    if player.dead then return end
    local use = U.askForPlayCard(player.room, player, nil, nil, "xiaobai__huihao",
      "#xiaobai__huihao-use", {bypass_times = true, extraUse = true}, true)
    if not use then return end
    local suit = use.card:getSuitString()
    room:useCard(use)
    if player.dead or not room:askForSkillInvoke(player, "xiaobai__huihao", nil, "#xiaobai__huihao-invoke") then return end
    room:doIndicate(player.id, table.map(room:getOtherPlayers(player), Util.IdMapper))
    local pattern = ".|.|"..suit
    for _, p in ipairs(room:getOtherPlayers(player)) do
      if player.dead then return end
      if not p.dead and not p:isNude() then
        local all_choices = {
          "xiaobai__huihao_give:"..player.id.."::"..suit,
          "xiaobai__huihao_slash:"..player.id,
        }
        local choices = table.simpleClone(all_choices)
        if not table.find(p:getCardIds("he"), function (id)
          return Fk:getCardById(id):getSuitString() == suit
        end) then
          table.remove(choices, 1)
        end
        if #table.filter(p:getCardIds("he"), function (id)
          return not p:prohibitDiscard(id)
        end) < 2 then
          table.remove(choices, #choices)
        end
        if #choices > 0 then
          local choice = room:askForChoice(p, choices, "xiaobai__huihao", nil, false, all_choices)
          if choice[17] == "g" then
            local card = room:askForCard(p, 1, 1, true, "xiaobai__huihao", false, pattern,
              "#xiaobai__huihao-ask:"..player.id.."::"..suit)
            room:moveCardTo(card, Card.PlayerHand, player, fk.ReasonGive, "xiaobai__huihao", nil, true, p.id,
              "@@xiaobai__huihao-inhand-turn")
          else
            room:askForDiscard(p, 2, 2, true, "xiaobai__huihao", false, nil, "#xiaobai__huihao-slash:"..player.id)
            if not player.dead then
              room:useVirtualCard("slash", nil, p, player, "xiaobai__huihao", true)
            end
          end
        end
      end
    end
  end,
}
local huihao_targetmod = fk.CreateTargetModSkill{
  name = "#xiaobai__huihao_targetmod",
  bypass_distances = function (self, player, skill, card, to)
    return card and table.contains(card.skillNames, "xiaobai__huihao")
  end,
  bypass_times = function(self, player, skill, scope, card, to)
    return card and table.contains(card.skillNames, "xiaobai__huihao")
  end,
}
local weilv = fk.CreateActiveSkill{
  name = "xiaobai__weilv",
  anim_type = "drawcard",
  min_card_num = 1,
  max_card_num = 2,
  target_num = 0,
  prompt = function (self, selected_cards)
    return "#"..self.interaction.data
  end,
  interaction = function(self)
    local all_choices, choices = {}, {}
    for i = 1, 3, 1 do
      table.insert(all_choices, "xiaobai__weilv"..i)
      if Self:getMark("xiaobai__weilv"..i.."-phase") == 0 then
        table.insert(choices, "xiaobai__weilv"..i)
      end
    end
    return UI.ComboBox { choices = choices, all_choices = all_choices }
  end,
  can_use = function (self, player)
    for i = 1, 3, 1 do
      if player:getMark("xiaobai__weilv"..i.."-phase") == 0 then
        return true
      end
    end
  end,
  card_filter = function(self, to_select, selected)
    local card = Fk:getCardById(to_select)
    if not Self:prohibitDiscard(to_select) then
      if self.interaction.data == "xiaobai__weilv1" then
        return #selected == 0 and card.trueName == "slash"
      elseif self.interaction.data == "xiaobai__weilv2" then
        return #selected == 0 and card.trueName == "jink"
      elseif self.interaction.data == "xiaobai__weilv3" then
        return #selected < 2 and card.type == Card.TypeBasic
      end
    end
  end,
  feasible = function (self, selected, selected_cards)
    if self.interaction.data == "xiaobai__weilv1" then
      return #selected_cards == 1
    elseif self.interaction.data == "xiaobai__weilv2" then
      return #selected_cards == 1
    elseif self.interaction.data == "xiaobai__weilv3" then
      return #selected_cards == 2
    end
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    room:setPlayerMark(player, self.interaction.data.."-phase", 1)
    room:throwCard(effect.cards, self.name, player, player)
    if player.dead then return end
    player:drawCards(#effect.cards, self.name)
    if player.dead then return end
    room:addPlayerMark(player, "@@"..self.interaction.data, 1)
    if self.interaction.data == "xiaobai__weilv3" then
      room:endTurn()
    end
  end,
}
local weilv_trigger = fk.CreateTriggerSkill{
  name = "#xiaobai__weilv_trigger",
  mute = true,
  events = {fk.CardUsing},
  can_trigger = function(self, event, target, player, data)
    if player:getMark("@@xiaobai__weilv1") > 0 then
      if data.card.trueName == "jink" then
        return true
      end
    end
    if player:getMark("@@xiaobai__weilv2") > 0 then
      if data.card.trueName == "slash" then
        return true
      end
    end
    if player:getMark("@@xiaobai__weilv3") > 0 then
      if data.card.type == Card.TypeBasic or data.card:isCommonTrick() then
        return true
      end
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    local room = player.room
    player:broadcastSkillInvoke("xiaobai__weilv")
    room:notifySkillInvoked(player, "xiaobai__weilv", "control")
    data.tos = {}
    room:setPlayerMark(player, "@@xiaobai__weilv3", 0)
    if data.card.trueName == "jink" then
      room:setPlayerMark(player, "@@xiaobai__weilv1", 0)
    end
    if data.card.trueName == "slash" then
      room:setPlayerMark(player, "@@xiaobai__weilv2", 0)
    end
  end,
}
huihao:addRelatedSkill(huihao_trigger)
huihao:addRelatedSkill(huihao_targetmod)
weilv:addRelatedSkill(weilv_trigger)
zhaoyu:addSkill(huihao)
zhaoyu:addSkill(weilv)
Fk:loadTranslationTable{
  ["xiaobai__zhaoyu"] = "赵妪",
  ["#xiaobai__zhaoyu"] = "踅驳高秋",
  ["illustrator:xiaobai__zhaoyu"] = "丞惡浪",
  ["designer:xiaobai__zhaoyu"] = "柠檬",

  ["xiaobai__huihao"] = "麾号",
  [":xiaobai__huihao"] = "准备阶段，你可以摸一张牌并使用一张牌，然后你令所有其他角色依次选择一项: 1.交给你一张花色相同的牌，"..
  "这些牌本回合可以当无次数限制的【杀】使用; 2.弃置两张花色不同的牌，视为对你使用火【杀】。",
  ["xiaobai__weilv"] = "威旅",
  [":xiaobai__weilv"] = "出牌阶段各限一次，你可以：<br>1.弃置一张【杀】令下一张被使用的【闪】无效；<br>2.弃置一张【闪】令下一张"..
  "被使用的【杀】无效；<br>3.弃置两张基本牌，令下一张被使用的基本牌或普通锦囊牌无效且本回合结束。<br>选择完成后，你摸X张牌（X为你弃置牌的数量）。",
  ["#xiaobai__huihao-use"] = "麾号：你可以使用一张牌",
  ["#xiaobai__huihao-invoke"] = "麾号：是否令其他角色依次选择交给你牌或对你使用【杀】？",
  ["#xiaobai__huihao-ask"] = "麾号：请交给 %src 一张%arg牌，此牌本回合可以当【杀】使用",
  ["@@xiaobai__huihao-inhand-turn"] = "麾号",
  ["xiaobai__huihao_give"] = "交给%src一张%arg牌，此牌本回合可以当无距离次数限制的【杀】使用",
  ["xiaobai__huihao_slash"] = "弃置两张牌，视为对%src使用【杀】",
  ["#xiaobai__huihao_trigger"] = "麾号",
  ["#xiaobai__huihao-slash"] = "麾号：请弃置两张牌，视为对 %src 使用【杀】",
  ["#xiaobai__huihao"] = "麾号：你可以将“麾号”牌当无距离次数限制的【杀】使用",
  ["#xiaobai__weilv1"] = "威旅：弃置一张【杀】令下一张被使用的【闪】无效",
  ["#xiaobai__weilv2"] = "威旅：弃置一张【闪】令下一张被使用的【杀】无效",
  ["#xiaobai__weilv3"] = "威旅：弃置两张基本牌，令下一张被使用的基本牌或普通锦囊牌无效且本回合结束",
  ["xiaobai__weilv1"] = "弃置一张【杀】下一张【闪】无效",
  ["xiaobai__weilv2"] = "弃置一张【闪】下一张【杀】无效",
  ["xiaobai__weilv3"] = "弃置两张基本牌，令下一张基本牌或普通锦囊牌无效且本回合结束",
  ["@@xiaobai__weilv1"] = "威旅 闪无效",
  ["@@xiaobai__weilv2"] = "威旅 杀无效",
  ["@@xiaobai__weilv3"] = "威旅 即时牌无效",
  ["#xiaobai__weilv_trigger"] = "威旅",
}

local xiyingxi = General(extension, "xiaobai__xiyingxi", "wu", 3, 3, General.Female)
--[[local duanhuo = fk.CreateViewAsSkill{
  name = "xiaobai__duanhuo",
  anim_type = "control",
  prompt = "#xiaobai__duanhuo",
  card_filter = Util.FalseFunc,
  view_as = function(self, cards)
    local card = Fk:cloneCard("sincere_treat")
    card.skillName = self.name
    return card
  end,
  after_use = function (self, player, use)
    local room = player.room
    for _, id in ipairs(TargetGroup:getRealTargets(use.tos)) do
      local p = room:getPlayerById(id)
      if not p.dead and not p.chained and room:askForSkillInvoke(p, self.name, nil, "#xiaobai__duanhuo-ask") then
        p:setChainState(true)
      end
    end
  end,
  enabled_at_play = function (self, player)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
  end,
}
local duanhuo_targetmod = fk.CreateTargetModSkill{
  name = "#xiaobai__duanhuo_targetmod",
  bypass_distances = function(self, player, skill, card)
    return card and table.contains(card.skillNames, "xiaobai__duanhuo")
  end,
}]]--
local duanhuo = fk.CreateActiveSkill{
  name = "xiaobai__duanhuo",
  anim_type = "control",
  prompt = "#xiaobai__duanhuo",
  card_num = 0,
  target_num = 1,
  times = function (self)
    return Self.phase == Player.Play and 1 - Self:usedSkillTimes(self.name, Player.HistoryPhase) or -1
  end,
  can_use = function(self, player)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
  end,
  card_filter = Util.FalseFunc,
  target_filter = function (self, to_select, selected)
    return #selected == 0 and to_select ~= Self.id and not Fk:currentRoom():getPlayerById(to_select):isKongcheng()
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    local target = room:getPlayerById(effect.tos[1])
    local n = target:getHandcardNum()
    room:moveCardTo(target:getCardIds("h"), Card.PlayerHand, player, fk.ReasonPrey, self.name, nil, false, player.id)
    if player.dead or target.dead or player:isKongcheng() then return end
    local cards = room:askForCard(player, n, n, false, self.name, false, nil, "#xiaobai__duanhuo-give::"..target.id..":"..n)
    room:moveCardTo(cards, Card.PlayerHand, target, fk.ReasonGive, self.name, nil, false, player.id)
    if not target.dead and not target.chained and room:askForSkillInvoke(target, self.name, nil, "#xiaobai__duanhuo-ask") then
      target:setChainState(true)
    end
  end
}
local nirao = fk.CreateTriggerSkill{
  name = "xiaobai__nirao",
  anim_type = "support",
  events = {fk.AfterCardsMove},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) and player:usedSkillTimes(self.name, Player.HistoryTurn) == 0 then
      for _, move in ipairs(data) do
        if move.from and player.room:getPlayerById(move.from).chained and
          not table.contains({fk.ReasonUse, fk.ReasonResonpse}, move.moveReason) then
          for _, info in ipairs(move.moveInfo) do
            if info.fromArea == Card.PlayerHand or info.fromArea == Card.PlayerEquip then
              return true
            end
          end
        end
      end
    end
  end,
  on_trigger = function(self, event, target, player, data)
    local room = player.room
    local targets = {}
    for _, move in ipairs(data) do
      if move.from and room:getPlayerById(move.from).chained and
        not table.contains({fk.ReasonUse, fk.ReasonResonpse}, move.moveReason) then
        for _, info in ipairs(move.moveInfo) do
          if info.fromArea == Card.PlayerHand or info.fromArea == Card.PlayerEquip then
            table.insertIfNeed(targets, move.from)
          end
        end
      end
    end
    room:sortPlayersByAction(targets)
    for _, id in ipairs(targets) do
      if player:usedSkillTimes(self.name, Player.HistoryTurn) > 0 or not player:hasSkill(self) then break end
      local p = room:getPlayerById(id)
      if not p.dead then
        self:doCost(event, p, player, data)
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    return player.room:askForSkillInvoke(player, self.name, nil, "#xiaobai__nirao-invoke::"..target.id)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    room:doIndicate(player.id, {target.id})
    target:drawCards(2, self.name)
    if target:getHandcardNum() > target.maxHp and not target.dead and target.chained then
      target:setChainState(false)
    end
  end,
}
--duanhuo:addRelatedSkill(duanhuo_targetmod)
xiyingxi:addSkill(duanhuo)
xiyingxi:addSkill(nirao)
Fk:loadTranslationTable{
  ["xiaobai__xiyingxi"] = "习英习",
  ["#xiaobai__xiyingxi"] = "贵而能贫",
  ["illustrator:xiaobai__xiyingxi"] = "NOVART",
  ["designer:xiaobai__xiyingxi"] = "胖即是胖",
  ["cv:xiaobai__xiyingxi"] = "桃妮儿",

  ["xiaobai__duanhuo"] = "断祸",
  --[":xiaobai__duanhuo"] = "出牌阶段限一次，你可以视为使用一张无距离限制的【推心置腹】，然后目标角色需选择是否横置自己。",
  [":xiaobai__duanhuo"] = "出牌阶段限一次，你可以获得一名其他角色所有手牌并交给其等量手牌，然后其可以横置自己。",
  ["xiaobai__nirao"] = "逆饶",
  [":xiaobai__nirao"] = "每名角色的回合限一次，一名角色不因使用或打出失去牌后，若其已横置，你可以令其摸两张牌，然后若其手牌数大于体力上限，"..
  "重置其武将牌。",
  --["#xiaobai__duanhuo"] = "断祸：视为使用一张无距离限制的【推心置腹】，然后目标选择是否横置武将牌",
  ["#xiaobai__duanhuo"] = "断祸：获得一名其他角色所有手牌并交给其等量手牌，然后其可以横置武将牌",
  ["#xiaobai__duanhuo-give"] = "断祸：请交给 %dest %arg张手牌",
  ["#xiaobai__duanhuo-ask"] = "断祸：是否横置你的武将牌？",
  ["#xiaobai__nirao-invoke"] = "逆饶：是否令 %dest 摸两张牌？",

  ["$xiaobai__duanhuo1"] = "君偏见一时利害，忘究始终也。",
  ["$xiaobai__duanhuo2"] = "法天运者，福祸有常，取舍无定。",
  ["$xiaobai__nirao1"] = "君当自囚诣狱，显求受罪，或可逆见优饶。",
  ["$xiaobai__nirao2"] = "琅琊王好善慕名，不杀君明矣。",
  ["~xiaobai__xiyingxi"] = "幽明路歧，月圆分镜，留语复谁知？"
}


local cuifu = General(extension, "xiaobai__cuifu", "wei", 3, 3, General.Female)
local nichang = fk.CreateViewAsSkill{
  name = "xiaobai__nichang",
  pattern = ".|.|.|.|.|basic",
  prompt = "#xiaobai__nichang",
  interaction = function(self)
    local all_names = U.getAllCardNames("b")
    local names = U.getViewAsCardNames(Self, self.name, all_names, {}, Self:getTableMark("xiaobai__nichang-round"))
    if #names > 0 then
      return U.CardNameBox { choices = names, all_choices = all_names }
    end
  end,
  card_filter = Util.FalseFunc,
  view_as = function(self, cards)
    if not self.interaction.data then return end
    local card = Fk:cloneCard(self.interaction.data)
    card.skillName = self.name
    return card
  end,
  before_use = function(self, player, use)
    local room = player.room
    room:addTableMark(player, "xiaobai__nichang-round", use.card.trueName)
    local suits = {}
    for _, id in ipairs(player:getCardIds("h")) do
      table.insertIfNeed(suits, Fk:getCardById(id).suit)
    end
    table.removeOne(suits, Card.NoSuit)
    if #suits > 0 then
      for i = 1, #suits, 1 do
        if player.dead or player:isAllNude() then
          return self.name
        end
        local suit = player:getTableMark("@xiaobai__nichang")[1]
        local pattern = ".|.|"..U.ConvertSuit(suit, "sym", "str")
        local card = room:askForCard(player, 1, 1, true, self.name, true, pattern,
          "#xiaobai__nichang-ask:::"..suit..":"..(#suits + 1 - i), player:getCardIds("j"))
        if #card > 0 then
          local mark = player:getTableMark("@xiaobai__nichang")
          table.remove(mark, 1)
          table.insert(mark, suit)
          room:setPlayerMark(player, "@xiaobai__nichang", mark)
          room:recastCard(card, player, self.name)
        else
          return self.name
        end
      end
    end
  end,
  enabled_at_play = function (self, player)
    return player:getMark("@xiaobai__nichang") ~= 0
  end,
  enabled_at_response = function(self, player, response)
    return not response and player:getMark("@xiaobai__nichang") ~= 0
  end,

  on_acquire = function (self, player, is_start)
    player.room:setPlayerMark(player, "@xiaobai__nichang", {"log_heart", "log_spade", "log_club", "log_diamond"})
  end,
  on_lose = function (self, player, is_death)
    player.room:setPlayerMark(player, "@xiaobai__nichang", 0)
  end,
}
local nichang_trigger = fk.CreateTriggerSkill{
  name = "#xiaobai__nichang_trigger",
  anim_type = "control",
  events = {fk.CardUsing},
  can_trigger = function (self, event, target, player, data)
    return target == player and #player:getTableMark("xiaobai__nichang-round") == 4 and
      table.contains(data.card.skillNames, "xiaobai__nichang") and
      #player.room:getOtherPlayers(player) > 0
  end,
  on_cost = Util.TrueFunc,
  on_use = function (self, event, target, player, data)
    local room = player.room
    room:doIndicate(player.id, table.map(room:getOtherPlayers(player), Util.IdMapper))
    for _, p in ipairs(room:getOtherPlayers(player)) do
      p:turnOver()
    end
  end,
}
local diaodie = fk.CreateTriggerSkill{
  name = "xiaobai__diaodie",
  anim_type = "defensive",
  frequency = Skill.Compulsory,
  events = {fk.PreCardEffect},
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self) and data.to == player.id and data.from ~= player.id and data.card.is_damage_card and
      #player:getTableMark("@xiaobai__nichang") > 0 and data.card:getSuitString(true) == player:getMark("@xiaobai__nichang")[1]
  end,
  on_use = function (self, event, target, player, data)
    local room = player.room
    local choice = room:askForChoice(player, {"xiaobai__diaodie1:::"..data.card:getSuitString(true), "xiaobai__diaodie2"}, self.name)
    if choice == "xiaobai__diaodie2" then
      room:loseHp(player, 1, self.name)
      if not player.dead and #player:getTableMark("@xiaobai__nichang") < 4 then
        local suits = {}
        for _, suit in ipairs({"heart", "spade", "club", "diamond"}) do
          if not table.contains(player:getTableMark("@xiaobai__nichang"), "log_"..suit) then
            table.insert(suits, suit)
          end
        end
        local cards = {}
        for _, suit in ipairs(suits) do
          table.insertTable(cards, room:getCardsFromPileByRule(".|.|"..suit))
        end
        if #cards > 0 then
          room:moveCardTo(cards, Card.PlayerHand, player, fk.ReasonJustMove, self.name, nil, false, player.id)
        end
      end
    else
      local mark = player:getTableMark("@xiaobai__nichang")
      table.removeOne(mark, data.card:getSuitString(true))
      if #mark == 0 then
        room:setPlayerMark(player, "@xiaobai__nichang", 0)
      else
        local new_mark = {}
        for _, suit in ipairs({"log_heart", "log_spade", "log_club", "log_diamond"}) do
          if table.contains(mark, suit) then
            table.insert(new_mark, suit)
          end
        end
        room:setPlayerMark(player, "@xiaobai__nichang", new_mark)
      end
    end
    return true
  end,
}
nichang:addRelatedSkill(nichang_trigger)
cuifu:addSkill(nichang)
cuifu:addSkill(diaodie)
Fk:loadTranslationTable{
  ["xiaobai__cuifu"] = "崔芣",
  ["#xiaobai__cuifu"] = "绫蝶枝折",
  ["illustrator:xiaobai__cuifu"] = "久梓",
  ["designer:xiaobai__cuifu"] = "左小白",

  ["xiaobai__nichang"] = "霓裳",
  [":xiaobai__nichang"] = "转换技，当你需使用本轮未声明过的基本牌时，你可以声明之，然后重铸你区域内的一张①<font color='red'>♥</font>②♠③♣"..
  "④<font color='red'>♦</font>牌，以此法重铸X张牌后你视为使用之；当你本轮第四次以此法使用牌时，你令所有其他角色翻面。（X为你手牌中的花色数）",
  ["xiaobai__diaodie"] = "凋蝶",
  [":xiaobai__diaodie"] = "锁定技，其他角色对你使用的与〖霓裳〗当前转换项相同花色的伤害类牌对你生效前，改为令你选择一项：<br>"..
  "1.删去该转换项并重置〖霓裳〗花色顺序；<br>2.失去1点体力，从牌堆中获得〖霓裳〗中被删去的花色牌各一张。",
  ["#xiaobai__nichang"] = "霓裳：声明你要使用的牌和目标，然后重铸对应花色的牌以视为使用之",
  ["#xiaobai__nichang-ask"] = "霓裳：请重铸一张%arg牌（再重铸%arg2张则视为使用！）",
  ["@xiaobai__nichang"] = "霓裳",
  ["#xiaobai__nichang_trigger"] = "霓裳",
  ["xiaobai__diaodie1"] = "删去%arg项并重置〖霓裳〗花色顺序",
  ["xiaobai__diaodie2"] = "失去1点体力，获得〖霓裳〗被删去花色牌各一张",
}

local hushi = General(extension, "xiaobai__hushi", "shu", 3, 3, General.Female)
local huoyan = fk.CreateViewAsSkill{
  name = "xiaobai__huoyan",
  pattern = ".|.|.|.|.|basic",
  prompt = "#xiaobai__huoyan",
  interaction = function(self)
    local all_names = U.getAllCardNames("b")
    local names = U.getViewAsCardNames(Self, self.name, all_names)
    if #names > 0 then
      return U.CardNameBox { choices = names, all_choices = all_names }
    end
  end,
  card_filter = Util.FalseFunc,
  view_as = function(self, cards)
    if not self.interaction.data then return end
    local card = Fk:cloneCard(self.interaction.data)
    card.skillName = self.name
    return card
  end,
  before_use = function(self, player)
    local room = player.room
    local targets = table.filter(room:getOtherPlayers(player), function(p)
      return p:canMoveCardsInBoardTo(player)
    end)
    local to = room:askForChoosePlayers(player, table.map(targets, Util.IdMapper), 1, 1, "#xiaobai__huoyan-choose", self.name, false)
    to = room:getPlayerById(to[1])
    local result = room:askForMoveCardInBoard(player, to, player, self.name, nil, to)
    if result.card.type == Card.TypeEquip and not player.dead and player:hasSkill(self.name, true) then
      room:setPlayerMark(player, "@@xiaobai__huoyan", 1)
    end
  end,
  enabled_at_play = function(self, player)
    return player:getMark("@@xiaobai__huoyan") == 0 and table.find(Fk:currentRoom().alive_players, function(p)
      return p:canMoveCardsInBoardTo(player)
    end)
  end,
  enabled_at_response = function(self, player, response)
    return not response and player:getMark("@@xiaobai__huoyan") == 0 and
      table.find(Fk:currentRoom().alive_players, function(p)
        return p:canMoveCardsInBoardTo(player)
      end)
  end,
}
local huoyan_delay = fk.CreateTriggerSkill{
  name = "#xiaobai__huoyan_delay",

  refresh_events = {fk.AfterCardsMove, fk.EventLoseSkill},
  can_refresh = function(self, event, target, player, data)
    if player:getMark("@@xiaobai__huoyan") > 0 then
      if event == fk.AfterCardsMove then
        for _, move in ipairs(data) do
          if move.from == player.id then
            for _, info in ipairs(move.moveInfo) do
              if Fk:getCardById(info.cardId).type == Card.TypeEquip then
                return true
              end
            end
          end
        end
      elseif event == fk.EventLoseSkill then
        return target == player and data == self
      end
    end
  end,
  on_refresh = function(self, event, target, player, data)
    player.room:setPlayerMark(player, "@@xiaobai__huoyan", 0)
  end,
}
local yanzai = fk.CreateTriggerSkill{
  name = "xiaobai__yanzai",
  switch_skill_name = "xiaobai__yanzai",
  anim_type = "negative",
  events = {fk.CardUseFinished},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) and target ~= player and data.card.type == Card.TypeEquip and not target.dead and
      not table.find(player.room.alive_players, function (p)
        return p.dying
      end) then
      if player:getSwitchSkillState(self.name, false) == fk.SwitchYang then
        return target:canUseTo(Fk:cloneCard("dismantlement"), player)
      elseif player:getSwitchSkillState(self.name, false) == fk.SwitchYin then
        return target:canUseTo(Fk:cloneCard("collateral"), player)
      end
    end
  end,
  on_cost = function (self, event, target, player, data)
    local name = "dismantlement"
    if player:getSwitchSkillState(self.name, false) == fk.SwitchYin then
      name = "collateral"
    end
    local use = U.askForUseVirtualCard(player.room, target, name, nil, self.name,
      "#xiaobai__yanzai-use:"..player.id.."::"..name, true, false, false, false, {must_targets = {player.id}}, true)
    if use then
      self.cost_data = use
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    room:setPlayerMark(player, "xiaobai__yanzai-turn", 1)
    room:useCard(self.cost_data)
  end,
}
local yanzai_delay = fk.CreateTriggerSkill{
  name = "#xiaobai__yanzai_delay",
  mute = true,
  events = {fk.BeforeCardsMove},
  can_trigger = function(self, event, target, player, data)
    if player:getMark("xiaobai__yanzai-turn") > 0 then
      for _, move in ipairs(data) do
        if move.from == player.id then
          for _, info in ipairs(move.moveInfo) do
            if table.contains({Card.PlayerHand, Card.PlayerEquip, Card.PlayerJudge}, info.fromArea) then
              return true
            end
          end
        end
      end
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function(self, event, target, player, data)
    local room = player.room
    room:setPlayerMark(player, "xiaobai__yanzai-turn", 0)
    local targets = room:getOtherPlayers(player)
    if #targets == 0 then return end
    local ids = {}
    for _, move in ipairs(data) do
      if move.from == player.id then
        for _, info in ipairs(move.moveInfo) do
          if table.contains({Card.PlayerHand, Card.PlayerEquip, Card.PlayerJudge}, info.fromArea) then
            table.insertIfNeed(ids, info.cardId)
          end
        end
      end
    end
    local to
    if #ids > 0 then
      local choice = U.askforViewCardsAndChoice(player, ids, {"OK", "Cancel"}, "xiaobai__yanzai", "#xiaobai__yanzai-invoke")
      if choice == "OK" then
        to = room:askForChoosePlayers(player, table.map(targets, Util.IdMapper), 1, 1,
          "#xiaobai__yanzai-give", "xiaobai__yanzai", false)
        to = room:getPlayerById(to[1])
      else
        return
      end
    end
    for _, move in ipairs(data) do
      if move.from == player.id then
        local new_info = {}
        for _, info in ipairs(move.moveInfo) do
          if table.contains(ids, info.cardId) then
            --continue
          else
            table.insert(new_info, info)
          end
          move.moveInfo = new_info
        end
      end
    end
    room:moveCardTo(ids, Card.PlayerHand, to, fk.ReasonGive, "xiaobai__yanzai", nil, true, player.id)
  end,
}
huoyan:addRelatedSkill(huoyan_delay)
yanzai:addRelatedSkill(yanzai_delay)
hushi:addSkill(huoyan)
hushi:addSkill(yanzai)
AddWinAudio(hushi)
Fk:loadTranslationTable{
  ["xiaobai__hushi"] = "胡氏",
  ["#xiaobai__hushi"] = "暗月炎花",
  ["illustrator:xiaobai__hushi"] = "隈研吾",
  ["designer:xiaobai__hushi"] = "虎鲸",

  ["xiaobai__huoyan"] = "火宴",
  [":xiaobai__huoyan"] = "你可以将其他角色场上一张牌移至你的场上，视为使用一张基本牌；若以此法移动装备牌，此技能失效直到你失去装备牌。",
  ["xiaobai__yanzai"] = "妟灾",
  [":xiaobai__yanzai"] = "转换技，其他角色使用装备牌后，若没有角色处于濒死状态，其可以视为对你使用①【过河拆桥】②【借刀杀人】，本回合下次有牌"..
  "离开你区域时，你可以将之交给一名其他角色。",
  ["#xiaobai__huoyan"] = "火宴：选择要使用的牌名和目标，然后将其他角色场上一张牌移至你场上以视为使用",
  ["#xiaobai__huoyan-choose"] = "火宴：选择一名角色将其场上的牌移至你场上，若为装备牌则此技能失效！",
  ["@@xiaobai__huoyan"] = "火宴失效",
  ["#xiaobai__yanzai-use"] = "妟灾：你可以视为对 %src 使用【%arg】",
  ["#xiaobai__yanzai_delay"] = "妟灾",
  ["#xiaobai__yanzai-invoke"] = "妟灾：是否将你即将失去的这些牌交给一名其他角色？",
  ["#xiaobai__yanzai-give"] = "妟灾：选择获得这些牌的角色",

  ["$xiaobai__huoyan1"] = "今日良宴，欢乐难陈；银灯一曲，同赴醉乡。",
  ["$xiaobai__huoyan2"] = "秦筝齐瑟，乐饮三爵，嘉宾满堂，烦疴消散。",
  ["$xiaobai__yanzai1"] = "乐不可极，极乐成哀；欲不可纵，纵欲成灾。",
  ["$xiaobai__yanzai2"] = "情爱过义、怠慢忘身；是以害胜慎、祸胜谨。",
  ["$xiaobai__hushi_win_audio"] = "世缘情爱总是空，夫妻至亲亦至疏。",
  ["~xiaobai__hushi"] = "草萤终非火，朝露岂是珠？"
}

local zhangyu = General(extension, "xiaobai__zhangyu", "shu", 3)
local xiongchen = fk.CreateTriggerSkill{
  name = "xiaobai__xiongchen",
  anim_type = "drawcard",
  frequency = Skill.Compulsory,
  events = {fk.StartJudge, fk.AfterDrawPileShuffle},
  can_trigger = function(self, event, target, player, data)
    if event == fk.StartJudge then
      return target == player and player:hasSkill(self)
    elseif event == fk.AfterDrawPileShuffle then
      local skill_event = player.room.logic:getCurrentEvent():findParent(GameEvent.SkillEffect, true)
      return skill_event and skill_event.data[3] == self and skill_event.data[2] == player
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.StartJudge then
      if data.card then --防止被咒缚等技能截胡
        room:moveCardTo(data.card, Card.DiscardPile, nil, fk.ReasonJustMove)
      end
      local cards = {}
      while true do
        local id = room:getNCards(1)[1]
        room:moveCardTo(id, Card.Processing, nil, fk.ReasonJustMove, self.name, nil, true, player.id)
        room:delay(1000)
        local card = Fk:getCardById(id)
        data.card = card  --防止二效果炸事件后clear中data.card为空报错
        if card.trueName == "slash" then
          break
        else
          table.insert(cards, id)
          room:setPlayerMark(player, self.name, cards)  --偷懒，用于二效果炸事件后清理处理区
        end
      end
      if #cards > 0 and not player.dead then
        room:moveCardTo(cards, Card.PlayerHand, player, fk.ReasonJustMove, self.name, nil, true, player.id)
      end
    else
      local e = room.logic:getCurrentEvent().parent
      while e do
        if e.event == GameEvent.SkillEffect and e.data[3] ~= self then
          room.logic:getCurrentEvent():addExitFunc(function()
            e:shutdown()
          end)
          local parent = e.parent
          if parent and parent.event == GameEvent.CardEffect then
            local effect = parent.data[1]
            if effect.card.sub_type == Card.SubtypeDelayedTrick and
              room:getCardArea(effect.card:getEffectiveId()) == Card.Processing and
              not target.dead and not target:hasDelayedTrick(effect.card.name) and
              not table.contains(target.sealedSlots, Player.JudgeSlot) then
              local card = effect.card
              if card:isVirtual() then
                card = Fk:cloneCard(card.name)
                card:addSubcards(effect.card.subcards)
                card.skillNames = effect.card.skillNames
                target:addVirtualEquip(card)
              end
              room:moveCardTo(card, Player.Judge, target, fk.ReasonJustMove, self.name)
            end
          end
          break
        end
        e = e.parent
      end
      local cards = table.filter(player:getTableMark(self.name), function (id)
        return room:getCardArea(id) == Card.Processing
      end)
      if #cards > 0 then
        room:moveCardTo(cards, Card.DiscardPile, nil, fk.ReasonJustMove)
      end
      local total = 3
      while total > 0 do
        room:setPlayerMark(player, "xiaobai__xiongchen-tmp", total)
        local _, dat = room:askForUseActiveSkill(player, "xiaobai__xiongchen_active",
          "#xiaobai__xiongchen-num:::"..total, false)
        local to = room:getPlayerById(dat.targets[1])
        room:addPlayerMark(to, "@xiaobai__xiongchen_count", dat.interaction)
        total = total - dat.interaction
      end
      for _, p in ipairs(room:getAlivePlayers()) do
        if p:getMark("@xiaobai__xiongchen_count") > 0 then
          room:damage{
            from = player,
            to = p,
            damage = p:getMark("@xiaobai__xiongchen_count"),
            damageType = fk.ThunderDamage,
            skillName = self.name,
          }
          room:setPlayerMark(p, "@xiaobai__xiongchen_count", 0)
        end
      end
    end
  end,
}
local xiongchen_active = fk.CreateActiveSkill{
  name = "xiaobai__xiongchen_active",
  card_num = 0,
  target_num = 1,
  interaction = function()
    return UI.Spin {
      from = 1,
      to = Self:getMark("xiaobai__xiongchen-tmp"),
    }
  end,
  card_filter = Util.FalseFunc,
  target_filter = function (self, to_select, selected)
    return #selected == 0
  end,
}
local yanhuo = fk.CreateTriggerSkill{
  name = "xiaobai__yanhuo",
  switch_skill_name = "xiaobai__yanhuo",
  anim_type = "control",
  events = {fk.EventPhaseStart},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) then
      if target == player and player.phase == Player.Start then
        return player:getMark(self.name) > 0 or player:getSwitchSkillState(self.name, false) == fk.SwitchYang
      elseif target ~= player and target.phase == Player.Finish then
        return not target.dead and (player:getMark(self.name) > 0 or player:getSwitchSkillState(self.name, false) == fk.SwitchYin)
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    if target == player then
      return player.room:askForSkillInvoke(player, self.name, nil, "#xiaobai__yanhuo-yang")
    else
      return player.room:askForSkillInvoke(target, self.name, nil, "#xiaobai__yanhuo-yin:"..player.id)
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if target ~= player then
      room:doIndicate(target.id, {player.id})
    end
    local judge = {
      who = player,
      reason = "lightning",
      pattern = ".|2~9|spade",
    }
    room:judge(judge)
    if judge.card.suit == Card.Spade and judge.card.number > 1 and judge.card.number < 10 then
      local damage = {
        to = player,
        damage = 3,
        damageType = fk.ThunderDamage,
        skillName = self.name,
      }
      damage.extra_data = damage.extra_data or {}
      damage.extra_data.xiaobai__yanhuo = player.id
      room:damage(damage)
    end
    if player.dead then return end
    if player:getMark("xiaobai__yanhuo-tmp") > 0 then
      room:setPlayerMark(player, "xiaobai__yanhuo-tmp", 0)
      room:setPlayerMark(player, self.name, 1)
    --[[else
      local cards = room:getNCards(5, "bottom")
      room:moveCardTo(cards, Card.Processing, nil, fk.ReasonJustMove, self.name, nil, true, player.id)
      for i = 1, 2, 1 do
        if player.dead then break end
        if not U.askForUseRealCard(room, player, cards, nil, self.name, "#xiaobai__yanhuo-use",
          {
            bypass_times = true,
            extraUse = true,
            expand_pile = cards,
          }) then
          break
        end
        cards = table.filter(cards, function (id)
          return room:getCardArea(id) == Card.Processing
        end)
        if #cards == 0 then break end
      end
      if #cards > 0 and not player.dead then
        local result = room:askForGuanxing(player, cards, {0, 3}, nil, self.name, true, {"Top", "processing_area"})
        if #result.top > 0 then
          room:moveCards{
            ids = result.top,
            toArea = Card.DrawPile,
            moveReason = fk.ReasonJustMove,
            skillName = self.name,
            drawPilePosition = 1,
            moveVisible = true,
          }
        end
      end
      U.clearRemainCards(room, cards, self.name)]]
    end
  end,
  refresh_events = {fk.EnterDying},
  can_refresh = function(self, event, target, player, data)
    return data.damage and data.damage.skillName == self.name and
      data.damage.extra_data and data.damage.extra_data.xiaobai__yanhuo == player.id
  end,
  on_refresh = function(self, event, target, player, data)
    player.room:setPlayerMark(player, "xiaobai__yanhuo-tmp", 1)
  end,
}
Fk:addSkill(xiongchen_active)
zhangyu:addSkill(xiongchen)
zhangyu:addSkill(yanhuo)
Fk:loadTranslationTable{
  ["xiaobai__zhangyu"] = "张裕",
  ["#xiaobai__zhangyu"] = "天祸降人",
  ["illustrator:xiaobai__zhangyu"] = "NOVART",
  ["designer:xiaobai__zhangyu"] = "Mushi",
  ["cv:xiaobai__zhangyu"] = "cyc",

  ["xiaobai__xiongchen"] = "凶谶",
  [":xiaobai__xiongchen"] = "锁定技，你的判定流程改为依次亮出牌堆顶牌直到出现【杀】，你令此【杀】作为你的判定牌，然后获得其余亮出的牌；"..
  "若牌堆在此流程中洗牌，你分配3点雷电伤害并终止此次判定。",
  ["xiaobai__yanhuo"] = "言祸",
  [":xiaobai__yanhuo"] = "转换技，①准备阶段，你可以进行一次【闪电】判定;"..
  "②其他角色的结束阶段，其可以令你执行①项，若你因此进入濒死状态，删去“言祸”转换技标签。",
  ["xiaobai__xiongchen_active"] = "凶谶",
  ["#xiaobai__xiongchen-num"] = "凶谶：分配3点雷电伤害（还剩%arg点！）",
  ["@xiaobai__xiongchen_count"] = "伤害值",
  ["#xiaobai__yanhuo-yang"] = "言祸：是否进行一次【闪电】判定？",
  ["#xiaobai__yanhuo-yin"] = "言祸：是否令 %src 进行一次【闪电】判定？",
  ["#xiaobai__yanhuo-use"] = "言祸：你可以使用其中至多两张牌",

  ["$xiaobai__xiongchen1"] = "猝断之弦，其谶不远，汉中不可争。",
  ["$xiaobai__xiongchen2"] = "逆天政，背天情，丧天功，是之谓大凶。",
  ["$xiaobai__yanhuo1"] = "岁在庚子，天下易代，刘氏祚尽矣。",
  ["$xiaobai__yanhuo2"] = "得蜀不和，必有所失，算在寅卯之间。",
  ["~xiaobai__zhangyu"] = "周身稠密，头面稍稍，自知死兆至矣。"
}

local lishu = General(extension, "xiaobai__lishu", "qun", 4)
local xiongju = fk.CreateTriggerSkill{
  name = "xiaobai__xiongju",
  mute = true,
  frequency = Skill.Compulsory,
  events = {fk.AfterCardsMove, fk.TargetConfirming},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) then
      if event == fk.AfterCardsMove then
        local cards = {}
        for _, move in ipairs(data) do
          if move.toArea == Card.DiscardPile then
            if move.from and move.from ~= player.id then
              for _, info in ipairs(move.moveInfo) do
                if Fk:getCardById(info.cardId).is_damage_card and info.fromArea == Card.PlayerHand then
                  table.insertIfNeed(cards, info.cardId)
                end
              end
            elseif move.from == nil and
              table.contains({fk.ReasonUse, fk.ReasonResonpse, fk.ReasonPutIntoDiscardPile}, move.moveReason) then
              local parent_event = player.room.logic:getCurrentEvent().parent
              if parent_event ~= nil then
                local card_ids = {}
                if parent_event.event == GameEvent.UseCard or parent_event.event == GameEvent.RespondCard then
                  local use = parent_event.data[1]
                  if use.from ~= player.id and not use.damageDealt then
                    parent_event:searchEvents(GameEvent.MoveCards, 1, function(e2)
                      if e2.parent and e2.parent.id == parent_event.id then
                        for _, move2 in ipairs(e2.data) do
                          if (move2.moveReason == fk.ReasonUse or move2.moveReason == fk.ReasonResonpse) then
                            for _, info in ipairs(move2.moveInfo) do
                              if Fk:getCardById(info.cardId).is_damage_card and info.fromArea == Card.PlayerHand then
                                table.insertIfNeed(card_ids, info.cardId)
                              end
                            end
                          end
                        end
                      end
                    end)
                  end
                elseif parent_event.event == GameEvent.Pindian then
                  local pindian = parent_event.data[1]
                  if pindian.from ~= player then
                    card_ids = player.room:getSubcardsByRule(pindian.fromCard)
                  end
                  for id, dat in pairs(pindian.results) do
                    if id ~= player.id then
                      card_ids = player.room:getSubcardsByRule(dat.toCard)
                    end
                  end
                end
                if #card_ids > 0 then
                  for _, info in ipairs(move.moveInfo) do
                    if Fk:getCardById(info.cardId).is_damage_card and table.contains(card_ids, info.cardId) and
                      info.fromArea == Card.Processing then
                      table.insertIfNeed(cards, info.cardId)
                    end
                  end
                end
              end
            end
          end
        end
        cards = table.filter(cards, function (id)
          return table.contains(player.room.discard_pile, id)
        end)
        cards = U.moveCardsHoldingAreaCheck(player.room, cards)
        if #cards > 0 then
          self.cost_data = cards
          return true
        end
      elseif event == fk.TargetConfirming then
        if target == player and data.from ~= player.id and not player:isNude() then
          local from = player.room:getPlayerById(data.from)
          return from:getHandcardNum() < player:getHandcardNum() and from:inMyAttackRange(player)
        end
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    player:broadcastSkillInvoke(self.name)
    if event == fk.AfterCardsMove then
      room:notifySkillInvoked(player, self.name, "drawcard")
      room:moveCardTo(self.cost_data, Card.PlayerHand, player, fk.ReasonJustMove, self.name, nil, true, player.id)
    elseif event == fk.TargetConfirming then
      room:notifySkillInvoked(player, self.name, "negative")
      room:askForDiscard(player, 1, 1, true, self.name, false)
    end
  end,
}
local xiongju_attackrange = fk.CreateAttackRangeSkill{
  name = "#xiaobai__xiongju_attackrange",
  main_skill = xiongju,
  correct_func = function(self, from, to)
    for _, p in ipairs(Fk:currentRoom().alive_players) do
      if p ~= from and p:hasSkill(xiongju) and from:getHandcardNum() < p:getHandcardNum() and
        not (from:isRemoved() or p:isRemoved()) then
        local baseValue = 1
        local weapons = from:getEquipments(Card.SubtypeWeapon)
        if #weapons > 0 then
          baseValue = 0
          for _, id in ipairs(weapons) do
            local weapon = Fk:getCardById(id)
            baseValue = math.max(baseValue, weapon:getAttackRange(from) or 1)
          end
        end

        local status_skills = Fk:currentRoom().status_skills[AttackRangeSkill] or Util.DummyTable
        local max_fixed, correct = nil, 0
        for _, skill in ipairs(status_skills) do
          if skill ~= self then
            if skill:withoutAttackRange(from, p) then
              return 0
            end
            local f = skill:getFixed(from)
            if f ~= nil then
              max_fixed = max_fixed and math.max(max_fixed, f) or f
            end
            local c = skill:getCorrect(from)
            correct = correct + (c or 0)
          end
        end

        local n = math.max(math.max(baseValue, (max_fixed or 0)) + correct, 0)
        if from:distanceTo(p) < n then
          return from:distanceTo(p) - n
        end
      end
    end
  end,
}
local sige = fk.CreateActiveSkill{
  name = "xiaobai__sige",
  anim_type = "drawcard",
  card_num = 4,
  target_num = 0,
  prompt = "#xiaobai__sige",
  card_filter = function(self, to_select, selected)
    return #selected < 4
  end,
  can_use = function(self, player)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    room:recastCard(effect.cards, player, self.name)
    if player.dead then return end
    local targets = table.filter(room:getOtherPlayers(player), function (p)
      return player:inMyAttackRange(p)
    end)
    if #targets == 0 then return end
    local cards = table.filter(room.discard_pile, function (id)
      return Fk:getCardById(id).trueName == "slash"
    end)
    if #cards == 0 then return end
    local target = room:askForChoosePlayers(player, table.map(targets, Util.IdMapper), 1, 1,
      "#xiaobai__sige-choose", self.name, false)
    target = room:getPlayerById(target[1])
    local from, to = player, target
    local yes1, yes2, tag, nums = false, false, {}, {}
    while not player.dead and not target.dead do
      cards = table.filter(room.discard_pile, function (id)
        local card = Fk:getCardById(id)
        return card.trueName == "slash" and not table.contains(nums, card.number)
      end)
      if #cards == 0 then break end
      if table.find(cards, function (id)
        local card = Fk:getCardById(id)
        return from:canUseTo(card, to, {bypass_distances = true, bypass_times = true})
      end) then
        local use = U.askForUseRealCard(room, from, cards, "slash", self.name, "#xiaobai__sige-use", {
          bypass_distances = true,
          bypass_times = true,
          extraUse = true,
          expand_pile = cards,
          must_targets = {to.id},
        }, false, false)
        if use then
          table.insert(nums, use.card.number)
          if use.damageDealt then
            if use.damageDealt[player.id] then
              yes1 = true
            end
            if use.damageDealt[target.id] then
              yes2 = true
            end
            if yes1 and yes2 then
              break
            end
          end
        end
      else
        tag[from.id] = true
      end
      if tag[from.id] and tag[to.id] then
        break
      end
      if from == player then
        from, to = target, player
      else
        from, to = player, target
      end
    end
  end,
}
xiongju:addRelatedSkill(xiongju_attackrange)
lishu:addSkill(xiongju)
lishu:addSkill(sige)
AddWinAudio(lishu)
Fk:loadTranslationTable{
  ["xiaobai__lishu"] = "李术",
  ["#xiaobai__lishu"] = "鲸鲵栖江",
  ["illustrator:xiaobai__lishu"] = "孙启鑫",
  ["designer:xiaobai__lishu"] = "左小白",
  ["cv:xiaobai__lishu"] = "老班长与鱼刺",

  ["xiaobai__xiongju"] = "凶聚",
  [":xiaobai__xiongju"] = "锁定技，其他角色未造成过伤害的伤害类牌进入弃牌堆后，你获得之；其他角色手牌数小于你且你在其的攻击范围内时，其攻击范围"..
  "改为其与你的距离，且其使用【杀】或普通锦囊牌指定你为目标时，你须弃置一张牌。",
  ["xiaobai__sige"] = "肆戈",
  [":xiaobai__sige"] = "出牌阶段限一次，你可以重铸四张牌，然后指定一名攻击范围内的其他角色，你与其依次对对方使用弃牌堆中的一张【杀】，"..
  "直至你与其均因此受到伤害（每个点数的【杀】限一次）。",
  ["#xiaobai__sige"] = "肆戈：重铸四张牌，然后指定攻击范围内一名角色，你与其对对方使用弃牌堆中的【杀】！",
  ["#xiaobai__sige-choose"] = "肆戈：指定一名角色，你与其对对方使用弃牌堆中的【杀】！",
  ["#xiaobai__sige-use"] = "肆戈：对对方使用其中一张【杀】！",

  ["$xiaobai__xiongju1"] = "荣辱非命，大丈夫可自取！",
  ["$xiaobai__xiongju2"] = "吉凶择人，乃公为应劫之人！",
  ["$xiaobai__sige1"] = "鼎族高门，世禄绵延，某自横戈马上行！",
  ["$xiaobai__sige2"] = "不使其刀兵相杀，我等焉有露头日？",
  ["~xiaobai__lishu"] = "功名无过二字，性命原只数秋……",
  ["$xiaobai__lishu_win_audio"] = "大丈夫度日，自当专权势、作威福！"
}

local jiyan = General(extension, "xiaobai__jiyan", "wu", 3)
local function GaijuBetween(player, number)
  local numbers = table.map(player:getPile("xiaobai__jiyan_rule"), function (id)
    return Fk:getCardById(id).number
  end)
  return (number > numbers[1] and number < numbers[2]) or (number < numbers[1] and number > numbers[2])
end
AddWinAudio(jiyan)
local gaiju = fk.CreateTriggerSkill{
  name = "xiaobai__gaiju",
  mute = true,
  events = {fk.RoundStart, fk.CardUsing, fk.AfterCardsMove},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) then
      if event == fk.RoundStart then
        return #player:getPile("xiaobai__jiyan_rule") == 0
      elseif #player:getPile("xiaobai__jiyan_rule") == 2 then
        if event == fk.CardUsing then
          return target == player and not player:isNude() and #Card:getIdList(data.card) == 1 and
            not GaijuBetween(player, data.card.number)
        elseif event == fk.AfterCardsMove then
          for _, move in ipairs(data) do
            if move.from and move.from ~= player.id and move.moveReason == fk.ReasonDiscard then
              for _, info in ipairs(move.moveInfo) do
                if not GaijuBetween(player, Fk:getCardById(info.cardId).number) then
                  return true
                end
              end
            end
          end
        end
      end
    end
  end,
  on_cost = function (self, event, target, player, data)
    if event == fk.RoundStart then
      return player.room:askForSkillInvoke(player, self.name)
    else
      return true
    end
  end,
  on_use = function (self, event, target, player, data)
    local room = player.room
    player:broadcastSkillInvoke(self.name)
    if event == fk.RoundStart then
      room:notifySkillInvoked(player, self.name, "drawcard")
      player:drawCards(2, self.name)
      if player.dead or player:getHandcardNum() < 2 then return end
      local cards = room:askForCard(player, 2, 2, false, self.name, false, nil, "#xiaobai__gaiju-put")
      if Fk:getCardById(cards[1]).number > Fk:getCardById(cards[2]).number then
        cards[1], cards[2] = cards[2], cards[1]
      end
      player:addToPile("xiaobai__jiyan_rule", cards, true, self.name, player.id)
    elseif event == fk.CardUsing then
      room:notifySkillInvoked(player, self.name, "negative")
      room:askForDiscard(player, 1, 1, true, self.name, false)
    elseif event == fk.AfterCardsMove then
      room:notifySkillInvoked(player, self.name, "drawcard")
      player:drawCards(1, self.name)
    end
  end,
}
local suli = fk.CreateTriggerSkill{
  name = "xiaobai__suli",
  anim_type = "offensive",
  frequency = Skill.Compulsory,
  events = {fk.CardUsing},
  can_trigger = function(self, event, target, player, data)
    if target ~= player and player:hasSkill(self) and #player:getPile("xiaobai__jiyan_rule") == 2 and
      #Card:getIdList(data.card) == 1 then
      local turn_event = player.room.logic:getCurrentEvent():findParent(GameEvent.Turn)
      if turn_event == nil or turn_event.data[1] ~= target then return end
      return not GaijuBetween(player, data.card.number) and
        #player.room.logic:getEventsOfScope(GameEvent.UseCard, 2, function (e)
          local use = e.data[1]
          return use.from == target.id and not GaijuBetween(player, use.card.number)
        end, Player.HistoryTurn) == 1 and
        not target.dead
    end
  end,
  on_cost = function (self, event, target, player, data)
    if player.room:askForSkillInvoke(player, self.name, nil, "#xiaobai__suli-invoke::"..target.id) then
      self.cost_data = {tos = {target.id}}
      return true
    end
  end,
  on_use = function (self, event, target, player, data)
    local room = player.room
    room:damage{
      from = player,
      to = target,
      damage = 1,
      skillName = self.name,
    }
    if player.dead then return end
    local choices = {"xiaobai__suli2"}
    local cards = table.filter(player:getCardIds("he"), function (id)
      return GaijuBetween(player, Fk:getCardById(id).number)
    end)
    if #cards > 0 then
      table.insert(choices, 1, "xiaobai__suli1")
    end
    local choice = room:askForChoice(player, choices, self.name, nil, false, {"xiaobai__suli1", "xiaobai__suli2"})
    if choice == "xiaobai__suli1" then
      local card_data = {
        {"xiaobai__jiyan_rule", player:getPile("xiaobai__jiyan_rule")},
        {player.general, cards}
      }
      local ids = room:askForPoxi(player, self.name, card_data, nil, false)
      local id1, id2 = {}, {}
      for _, id in ipairs(ids) do
        if table.contains(cards, id) then
          table.insert(id1, id)
        else
          table.insert(id2, id)
        end
      end
      room:moveCards(
        {
          ids = id1,
          from = player.id,
          to = player.id,
          toArea = Card.PlayerSpecial,
          moveReason = fk.ReasonJustMove,
          specialName = "xiaobai__jiyan_rule",
          moveVisible = true,
          proposer = player.id,
        },
        {
          ids = id2,
          from = player.id,
          to = player.id,
          toArea = Card.PlayerHand,
          moveReason = fk.ReasonJustMove,
          fromSpecialName = "xiaobai__jiyan_rule",
          moveVisible = true,
          proposer = player.id,
        })
    else
      room:loseHp(player, 1, self.name)
      if not player.dead and #player:getPile("xiaobai__jiyan_rule") > 0 then
        room:recastCard(player:getPile("xiaobai__jiyan_rule"), player, self.name)
      end
    end
  end,
}
Fk:addPoxiMethod{
  name = "xiaobai__suli",
  prompt = "#xiaobai__suli",
  card_filter = function (to_select, selected, data, extra_data)
    if #selected < 2 then
      if #selected == 0 then
        return true
      else
        if table.contains(data[1][2], selected[1]) then
          return table.contains(data[2][2], to_select)
        else
          return table.contains(data[1][2], to_select)
        end
      end
    end
  end,
  feasible = function(selected, data)
    if data and #data == #selected and #selected == 2 then
      if table.contains(data[1][2], selected[1]) then
        return table.contains(data[2][2], selected[2])
      else
        return table.contains(data[1][2], selected[2])
      end
    end
  end,
  default_choice = function(data)
    if not data then return {} end
    local cids = {data[1][2][1], data[2][2][1]}
    return cids
  end,
}
jiyan:addSkill(gaiju)
jiyan:addSkill(suli)
Fk:loadTranslationTable{
  ["xiaobai__jiyan"] = "暨艳",
  ["#xiaobai__jiyan"] = "青竹折干",
  ["illustrator:xiaobai__jiyan"] = "凝聚永恒",
  ["designer:xiaobai__jiyan"] = "大祭司",
  ["cv:xiaobai__jiyan"] = "文小鸳",

  ["xiaobai__gaiju"] = "改矩",
  [":xiaobai__gaiju"] = "每轮开始时，若你没有“矩”，你可以摸两张牌并将两张手牌置于武将牌上，称为“矩”；你使用点数不为“矩”之间的牌时弃置一张牌，"..
  "其他角色弃置点数不为“矩”之间的牌后你摸一张牌。",

  ["$xiaobai__gaiju1"] = "碌碌庸人尸位禄，栋梁之才岂淹留！",
  ["$xiaobai__gaiju2"] = "倘若怀才，何居冗职？",


  ["xiaobai__suli"] = "肃吏",
  [":xiaobai__suli"] = "其他角色于其回合内首次使用点数不为“矩”之间的牌时，你可以对其造成1点伤害，然后你选择一项：<br>"..
  "1.用一张点数为“矩”之间的牌替换一张“矩”；<br>2.失去1点体力，然后重铸所有“矩”。",
  ["xiaobai__jiyan_rule"] = "矩",
  ["#xiaobai__gaiju-put"] = "改矩：请将两张手牌置为“矩”",
  ["#xiaobai__suli-invoke"] = "肃吏：是否对 %dest 造成1点伤害，然后选择一项？",
  ["xiaobai__suli1"] = "用一张点数为“矩”之间的牌替换一张“矩”",
  ["xiaobai__suli2"] = "失去1点体力并重铸所有“矩”",
  ["#xiaobai__suli"] = "肃吏：请交换一张“矩”",

  ["$xiaobai__suli1"] = "朝纲隳颓，清浊淆紊，自振衣奋袂，誓肃朝庭！",
  ["$xiaobai__suli2"] = "今墨吏尸位，而贤路壅塞，吾非泰山，岂徒坐视！",

  ["~xiaobai__jiyan"] = "割断私情、克成公法，盖吾之本心！",
  ["$xiaobai__jiyan_win_audio"] = "固执青山心不移，任他风雨四方袭！"
}

local peiqian = General(extension, "xiaobai__peiqian", "wei", 3)
local subei = fk.CreateTriggerSkill{
  name = "xiaobai__subei",
  anim_type = "control",
  events = {fk.EventPhaseStart},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and player.phase == Player.Play and
      table.find(player.room.alive_players, function (p)
        return not p:isNude()
      end)
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    if table.find(room:getOtherPlayers(player), function (p)
      return not p:isNude()
    end) or
      table.find(player:getCardIds("he"), function (id)
        return not player:prohibitDiscard(id)
      end) then
      return room:askForSkillInvoke(player, self.name, nil, "#xiaobai__subei-invoke")
    else
      room:askForCard(player, 1, 1, true, self.name, true, "false", "#xiaobai__subei-invoke")  --假装询问
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local orig_record = table.map(room.players, function (p)
      return p:getHandcardNum()
    end)
    local record = {}
    local total = 4
    while total > 0 do
      if player.dead then break end
      local targets = table.filter(room.alive_players, function (p)
        return table.find(p:getCardIds("he"), function (id)
          return not player:prohibitDiscard(id)
        end) ~= nil
      end)
      if #targets > 0 then
        local to = room:askForChoosePlayers(player, table.map(targets, Util.IdMapper), 1, 1,
          "#xiaobai__subei-choose:::"..total, self.name, total < 4)
        if #to > 0 then
          to = room:getPlayerById(to[1])
          if to == player then
            local cards = room:askForDiscard(player, 1, total, true, self.name, false, nil,
              "#xiaobai__subei-discard::"..to.id..":"..total, true)
            total = total - #cards
            record[to.id] = (record[to.id] or 0) + #cards
            room:throwCard(cards, self.name, player, player)
          else
            local cards = room:askForCardsChosen(player, to, 1, total, "he", self.name, "#xiaobai__subei-discard::"..to.id..":"..total)
            total = total - #cards
            record[to.id] = (record[to.id] or 0) + #cards
            room:throwCard(cards, self.name, to, player)
          end
        else
          break
        end
      else
        break
      end
    end
    local max, tos = 0, {}
    for id, num in pairs(record) do
      if max < num then
        max = num
        tos = {id}
      elseif max == num then
        table.insert(tos, id)
      end
    end
    room:sortPlayersByAction(tos)
    total = 0
    for _, id in ipairs(tos) do
      local p = room:getPlayerById(id)
      if not p.dead then
        total = total + 1
        p:drawCards(record[id], self.name)
      end
    end
    if total < 2 or player.dead then return end
    record = table.map(room.players, function (p)
      return p:getHandcardNum()
    end)
    local targets = {}
    for i = 1, #room.players, 1 do
      if record[i] == orig_record[i] and not room.players[i].dead then
        table.insert(targets, room.players[i])
      end
    end
    targets = table.filter(targets, function (p)
      return table.find(player:getMark(self.name), function (id)
          return player:canUseTo(Fk:getCardById(id), p, {bypass_distances = true, bypass_times = true})
        end)
    end)
    if #targets == 0 then return end
    local use = U.askForUseRealCard(room, player, player:getMark(self.name), nil, self.name, "#xiaobai__subei-slash",
      {
        bypass_distances = true,
        bypass_times = true,
        exclusive_targets = table.map(targets, Util.IdMapper),
        expand_pile = player:getMark(self.name),
      },
      true, false)
    if use then
      use = {
        card = Fk:cloneCard(use.card.name),
        from = player.id,
        tos = use.tos,
      }
      use.card.skillName = self.name
      use.extraUse = true
      room:useCard(use)
    end
  end,

  on_acquire = function (self, player, is_start)
    local room = player.room
    local cards = table.filter(U.getUniversalCards(room, "b"), function (id)
      return Fk:getCardById(id).trueName == "slash"
    end)
    room:setPlayerMark(player, self.name, cards)
  end,
}
local fulve = fk.CreateTriggerSkill{
  name = "xiaobai__fulve",
  anim_type = "control",
  events = {fk.EventPhaseStart},
  can_trigger = function(self, event, target, player, data)
    if target == player and player:hasSkill(self) and player.phase == Player.Finish then
      local room = player.room
      local targets = {}
      room.logic:getEventsOfScope(GameEvent.MoveCards, 1, function(e)
        for _, move in ipairs(e.data) do
          if move.to and move.toArea == Card.PlayerHand then
            table.insertIfNeed(targets, move.to)
          end
          if move.from then
            for _, info in ipairs(move.moveInfo) do
              if info.fromArea == Card.PlayerHand then
                table.insertIfNeed(targets, move.from)
              end
            end
          end
        end
      end, Player.HistoryTurn)
      if #targets == 0 then return end
      local record = {}
      room.logic:getEventsOfScope(GameEvent.MoveCards, 1, function(e)
        for _, move in ipairs(e.data) do
          if table.contains(targets, move.from) then
            for _, info in ipairs(move.moveInfo) do
              if info.fromArea == Card.PlayerHand or info.fromArea == Card.PlayerEquip then
                record[string.format("%.0f", move.from)] = (record[string.format("%.0f", move.from)] or 0) + 1
              end
            end
          end
        end
      end, Player.HistoryTurn)
      local targets1 = table.filter(targets, function (pId)
        local p = room:getPlayerById(pId)
        return table.find(U.getUniversalCards(room, "t"), function (id)
          local card = Fk:getCardById(id)
          return record[string.format("%.0f", pId)] == Fk:translate(card.trueName, "zh_CN"):len() and player:canUseTo(card, p)
        end)
      end)
      if #targets1 > 0 then
        self.cost_data = {targets1, 1, record}
        return true
      else
        targets1 = table.filter(targets, function (id)
          return id ~= player.id and not room:getPlayerById(id):isNude()
        end)
        if #targets1 > 0 then
          self.cost_data = {targets1, 2}
          return true
        end
      end
    end
  end,
  on_cost = function(self, event, target, player, data)
    local room = player.room
    if self.cost_data[2] == 1 then
      if not room:getBanner(self.name) then
        room:setBanner(self.name, U.getUniversalCards(room, "t"))
      end
      room:setPlayerMark(player, "xiaobai__fulve-tmp", self.cost_data[3])
      local success, dat = room:askForUseActiveSkill(player, "xiaobai__fulve_active", "#xiaobai__fulve-use", true)
      room:setPlayerMark(player, "xiaobai__fulve-tmp", 0)
      if success and dat then
        self.cost_data = {choice = 1, extra_data = dat}
        return true
      end
    else
      local to = room:askForChoosePlayers(player, self.cost_data[1], 1, 1, "#xiaobai__fulve-choose", self.name, false)
      self.cost_data = {tos = to, choice = 2}
      return true
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if self.cost_data.choice == 1 then
      local card = Fk:cloneCard(Fk:getCardById(self.cost_data.extra_data.cards[1]).name)
      card.skillName = self.name
      room:useCard{
        from = player.id,
        tos = table.map(self.cost_data.extra_data.targets, function(id) return {id} end),
        card = card,
      }
    else
      local to = room:getPlayerById(self.cost_data.tos[1])
      local card = room:askForCard(to, 1, 1, true, self.name, false, nil, "#xiaobai__fulve-give:"..player.id)
      room:moveCardTo(card, Card.PlayerHand, player, fk.ReasonGive, self.name, nil, false, to.id)
    end
  end,
}
local fulve_active = fk.CreateActiveSkill{
  name = "xiaobai__fulve_active",
  card_num = 1,
  min_target_num = 1,
  expand_pile = function (self)
    return Fk:currentRoom():getBanner("xiaobai__fulve")
  end,
  card_filter = function (self, to_select, selected)
    return #selected == 0 and table.contains(Fk:currentRoom():getBanner("xiaobai__fulve"), to_select)
  end,
  target_filter = function(self, to_select, selected, selected_cards, card, extra_data)
    if #selected_cards == 1 then
      local c = Fk:cloneCard(Fk:getCardById(selected_cards[1]).name)
      c.skillName = "xiaobai__fulve"
      if #selected == 0 then
        return Self:getMark("xiaobai__fulve-tmp")[string.format("%.0f", to_select)] == Fk:translate(c.trueName, "zh_CN"):len() and
          c.skill:modTargetFilter(to_select, {}, Self.id, c, false)
      elseif #selected == 1 then
        if c.skill:modTargetFilter(selected[1], {}, Self.id, c, false) then
          return c.skill:getMinTargetNum() > 1 and c.skill:targetFilter(to_select, selected, {}, c, extra_data)
        end
      end
    end
  end,
  feasible = function (self, selected, selected_cards)
    if #selected > 0 and #selected_cards == 1 then
      local card = Fk:cloneCard(Fk:getCardById(selected_cards[1]).name)
      card.skillName = "xiaobai__fulve"
      return card.skill:feasible(selected, {}, Self, card)
    end
  end,
  target_tip = function(self, to_select, selected, selected_cards, card, selectable)
    local info = Self:getMark("xiaobai__fulve-tmp")[string.format("%.0f", to_select)]
    if info then
      return "#xiaobai__fulve:::"..info
    else
      return
    end
  end,
}
Fk:addSkill(fulve_active)
peiqian:addSkill(subei)
peiqian:addSkill(fulve)
Fk:loadTranslationTable{
  ["xiaobai__peiqian"] = "裴潜",
  ["#xiaobai__peiqian"] = "撼北偕归",
  ["illustrator:xiaobai__peiqian"] = "NOVART",
  ["designer:xiaobai__peiqian"] = "我是兔子",

  ["xiaobai__subei"] = "肃北",
  [":xiaobai__subei"] = "出牌阶段开始时，你可以弃置任意名角色共计至多四张牌，然后弃置最多的角色摸等量张牌。若摸牌的角色数大于1，"..
  "你视为对其中手牌数与弃置之前相同的一名角色使用任意一种【杀】（无视距离）。",
  ["xiaobai__fulve"] = "抚略",
  [":xiaobai__fulve"] = "结束阶段，你可以视为对本回合手牌数变化过的一名角色使用一张牌名字数为X的普通锦囊牌，若你无法使用，你令本回合手牌数"..
  "变化过的其中一名其他角色交给你一张牌。（X为该角色本回合失去的牌数）",
  ["#xiaobai__subei-invoke"] = "肃北：是否发动“肃北”，弃置任意名角色共计至多四张牌？",
  ["#xiaobai__subei-choose"] = "肃北：你可以弃置一名角色的牌（还剩%arg张！）",
  ["#xiaobai__subei-discard"] = "肃北：弃置 %dest 至多%arg张牌",
  ["#xiaobai__subei-slash"] = "肃北：视为对其中一名角色使用一种【杀】",
  ["xiaobai__fulve_active"] = "抚略",
  ["#xiaobai__fulve-use"] = "抚略：你可以视为对其中一名角色使用一张牌名字数符合条件的锦囊牌",
  ["#xiaobai__fulve"] = "字数%arg",
  ["#xiaobai__fulve-choose"] = "抚略：令其中一名角色交给你一张牌",
  ["#xiaobai__fulve-give"] = "抚略：请交给 %src 一张牌",
}

local zhugerong = General(extension, "xiaobai__zhugerong", "wu", 3)
local xingzu = fk.CreateTriggerSkill{
  name = "xiaobai__xingzu",
  mute = true,
  frequency = Skill.Compulsory,
  events = {fk.GameStart, fk.AfterCardsMove, fk.Deathed},
  can_trigger = function(self, event, target, player, data)
    if event == fk.GameStart then
      return player:hasSkill(self) and #player.room:getOtherPlayers(player) > 0
    elseif event == fk.AfterCardsMove and player:hasSkill(self) and player:getMark("xiaobai__xingzu-turn") < 5 then
      for _, move in ipairs(data) do
        if move.from == player:getMark(self.name) and (move.moveReason == fk.ReasonResonpse or move.moveReason == fk.ReasonDiscard) then
          for _, info in ipairs(move.moveInfo) do
            if info.fromArea == Card.PlayerHand or info.fromArea == Card.PlayerEquip then
              return true
            end
          end
        end
      end
    elseif event == fk.Deathed then
      return player:getMark(self.name) == target.id
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    --player:broadcastSkillInvoke(self.name)
    if event == fk.GameStart then
      room:notifySkillInvoked(player, self.name, "special")
      local targets = table.map(room:getOtherPlayers(player), Util.IdMapper)
      local to = room:askForChoosePlayers(player, targets, 1, 1, "#xiaobai__xingzu-choose", self.name, false, false)
      to = room:getPlayerById(to[1])
      room:setPlayerMark(player, "@xiaobai__xingzu", to.general)
      room:setPlayerMark(player, self.name, to.id)
      player:broadcastSkillInvoke(self.name,1)
    elseif event == fk.AfterCardsMove then
      room:notifySkillInvoked(player, self.name, "drawcard")
      room:addPlayerMark(player, "xiaobai__xingzu-turn", 1)
      player:drawCards(1, self.name)
      player:broadcastSkillInvoke(self.name,2)
    elseif event == fk.Deathed then
      room:notifySkillInvoked(player, self.name, "negative")
      room:killPlayer({who = player.id})
    end
  end,

  refresh_events = {fk.DrawNCards},
  can_refresh = function (self, event, target, player, data)
    return target == player and
      table.find(player.room.alive_players, function (p)
        return p:getMark(self.name) == player.id
      end)
  end,
  on_refresh = function (self, event, target, player, data)
    data.n = data.n + #table.filter(player.room.alive_players, function (p)
      return p:getMark(self.name) == player.id
    end)
  end,
}
local xingzu_maxcards = fk.CreateMaxCardsSkill{
  name = "#xiaobai__xingzu_maxcards",
  correct_func = function(self, player)
    return #table.filter(Fk:currentRoom().alive_players, function (p)
      return p:getMark("xiaobai__xingzu") == player.id
    end)
  end,
}
local bowen = fk.CreateActiveSkill{
  name = "xiaobai__bowen",
  anim_type = "control",
  card_num = 0,
  target_num = 1,
  prompt = function (self, selected_cards, selected)
    if self.interaction.data == "xiaobai__bowen1" then
      return "#xiaobai__bowen1:::"..Self:getMark("xiaobai__bowen-phase")
    else
      return "#xiaobai__bowen2:::"..Self:getMark("xiaobai__bowen-phase")
    end
  end,
  times = function(self)
    return Self.phase == Player.Play and Self:getMark("xiaobai__bowen-phase") - Self:usedSkillTimes(self.name, Player.HistoryPhase) or -1
  end,
  interaction = function(self)
    local all_choices = {"xiaobai__bowen1"}
    local all_names = {}
    for _, name in ipairs(U.getAllCardNames("bt")) do
      if Fk:translate(Fk:cloneCard(name).trueName, "zh_CN"):len() == Self:getMark("xiaobai__bowen-phase") then
        table.insert(all_choices, name)
        table.insert(all_names, name)
      end
    end
    local choices = U.getViewAsCardNames(Self, self.name, all_names)
    table.insert(choices, 1, "xiaobai__bowen1")
    return U.CardNameBox {
      choices = choices,
      all_choices = all_choices,
      default_choice = "xiaobai__bowen1",
    }
  end,
  can_use = function(self, player)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) < player:getMark("xiaobai__bowen-phase")
  end,
  card_filter = Util.FalseFunc,
  target_filter = function (self, to_select, selected, selected_cards)
    if self.interaction.data == "xiaobai__bowen1" then
      return false
    else
      local card = Fk:cloneCard(self.interaction.data)
      card.skillName = self.name
      return card.skill:targetFilter(to_select, selected, {}, card, {bypass_times = true})
    end
  end,
  feasible = function (self, selected, selected_cards)
    if self.interaction.data == "xiaobai__bowen1" then
      return #selected == 0
    else
      local card = Fk:cloneCard(self.interaction.data)
      card.skillName = self.name
      return card.skill:feasible(selected, {}, Self, card)
    end
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    if self.interaction.data == "xiaobai__bowen1" then
      local to_discard = table.filter(player:getCardIds("he"), function (id)
        return not player:prohibitDiscard(id)
      end)
      local cards = room:askForPoxi(player, "xiaobai__bowen", {
        { "Top", room:getNCards(player:getMark("xiaobai__bowen-phase")) },
        { player.general, to_discard },
      }, nil, true)
      if #cards == 0 then return end
      local cards1 = table.filter(cards, function (id)
        return table.contains(to_discard, id)
      end)
      local cards2 = table.filter(cards, function (id)
        return table.contains(room.draw_pile, id)
      end)
      room:moveCards({
        ids = cards1,
        from = player.id,
        toArea = Card.DiscardPile,
        moveReason = fk.ReasonDiscard,
        skillName = self.name,
        proposer = player.id,
        moveVisible = true,
      },
      {
        ids = cards2,
        to = player.id,
        toArea = Card.PlayerHand,
        moveReason = fk.ReasonJustMove,
        skillName = self.name,
        proposer = player.id,
        moveVisible = true,
      })
    else
      local use = {
        from = player.id,
        tos = table.map(effect.tos, function (id) return {id} end),
        card = Fk:cloneCard(self.interaction.data),
        extraUse = true,
      }
      use.card.skillName = self.name
      room:useCard(use)
      player._phase_end = true
    end
  end,

  on_acquire = function (self, player, is_start)
    local room = player.room
    if player.phase == Player.Play then
      local events = room.logic:getEventsOfScope(GameEvent.UseCard, 5, function (e)
        return e.data[1].from == player.id
      end, Player.HistoryPhase)
      room:setPlayerMark(player, "xiaobai__bowen-phase", #events)
    end
  end,
}
Fk:addPoxiMethod{
  name = "xiaobai__bowen",
  prompt = function (data, extra_data)
    return "#xiaobai__bowen-exchange"
  end,
  card_filter = function(to_select, selected, data, extra_data)
    if table.contains(data[2][2], to_select) then
      return true
    else
      local n1, n2 = 0, 0
      for _, id in ipairs(selected) do
        local n = Fk:translate(Fk:getCardById(id).trueName, "zh_CN"):len()
        if table.contains(data[2][2], id) then
          n1 = n1 + n
        else
          n2 = n2 + n
        end
      end
      return n1 >= n2 + Fk:translate(Fk:getCardById(to_select).trueName, "zh_CN"):len()
    end
  end,
  feasible = function(selected, data, extra_data)
    if #selected > 0 then
      local n1, n2 = 0, 0
      for _, id in ipairs(selected) do
        local n = Fk:translate(Fk:getCardById(id).trueName, "zh_CN"):len()
        if table.contains(data[2][2], id) then
          n1 = n1 + n
        else
          n2 = n2 + n
        end
      end
      return n1 >= n2 and n2 > 0
    end
  end,
}
local bowen_delay = fk.CreateTriggerSkill{
  name = "#xiaobai__bowen_delay",

  refresh_events = {fk.AfterCardUseDeclared},
  can_refresh = function(self, event, target, player, data)
    return target == player and player:hasSkill(self, true) and player.phase == Player.Play and
      player:getMark("xiaobai__bowen-phase") < 5
  end,
  on_refresh = function(self, event, target, player, data)
    player.room:addPlayerMark(player, "xiaobai__bowen-phase", 1)
  end,
}
xingzu:addRelatedSkill(xingzu_maxcards)
bowen:addRelatedSkill(bowen_delay)
zhugerong:addSkill(xingzu)
zhugerong:addSkill(bowen)
Fk:loadTranslationTable{
  ["xiaobai__zhugerong"] = "诸葛融",
  ["#xiaobai__zhugerong"] = "崖岸之露",
  ["illustrator:xiaobai__zhugerong"] = "ArcNoir",
  ["designer:xiaobai__zhugerong"] = "七哀",
  ["cv:xiaobai__zhugerong"] = "张让",

  ["xiaobai__xingzu"] = "兴族",
  [":xiaobai__xingzu"] = "锁定技，游戏开始时，你选择一名其他角色：其摸牌阶段多摸一张牌且手牌上限+1；其因弃置或打出而失去牌后，你摸一张牌"..
  "（每回合至多摸5张）；其死亡后，你直接死亡。",
  ["xiaobai__bowen"] = "博文",
  [":xiaobai__bowen"] = "出牌阶段限X次，你可以选择一项：1.观看牌堆顶X张牌，然后可以弃置任意张牌，获得其中牌名字数之和不大于你弃置牌的牌；"..
  "2.视为使用一张牌名字数为X的基本牌或普通锦囊牌，然后本阶段结束。（X为你本阶段已使用的牌数，至多为5）",
  ["#xiaobai__xingzu-choose"] = "兴族：选择一名“兴族”目标角色",
  ["@xiaobai__xingzu"] = "兴族",
  ["#xiaobai__bowen1"] = "博文：观看牌堆顶%arg张牌，然后可以弃置牌获得其中的牌",
  ["#xiaobai__bowen2"] = "博文：视为使用字数为%arg的牌，然后本阶段结束",
  ["xiaobai__bowen1"] = "观看牌堆",
  ["#xiaobai__bowen-exchange"] = "博文：弃置任意张牌，获得牌名字数之和不大于弃牌的牌",

  ["$xiaobai__xingzu1"] = "父为国朝股肱，兄怀兴族大才，且乐其融融。",
  ["$xiaobai__xingzu2"] = "吾家通天之贵，奉我一身！",

  ["$xiaobai__bowen1"] = "何必为国之大器？聊以自乐耳。",
  ["$xiaobai__bowen2"] = "唯以博学，而成一世风流。",

  ["~xiaobai__zhugerong"] = "月满则亏……乐极生悲……"
}

return extension
